package com.spring.demo4.eg1;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

import java.lang.reflect.Method;

/**
 * @author vhans
 */
public class Test {
    @org.junit.Test
    public void test1() {
        UserService userService = new UserService();

        // 创建pointcut，用来拦截UserService中的work方法
        Pointcut pointcut = new Pointcut() {
            @Override
            public ClassFilter getClassFilter() {
                // 判断是否是UserService类型的
                return UserService.class::isAssignableFrom;
            }

            @Override
            public MethodMatcher getMethodMatcher() {
                return new MethodMatcher() {
                    @Override
                    public boolean matches(Method method, Class<?> targetClass) {
                        // 判断方法名是否是work
                        return "work".equals(method.getName());
                    }

                    @Override
                    public boolean isRuntime() {
                        // 动态参数匹配
                        return true;
                    }

                    @Override
                    public boolean matches(Method method, Class<?> targetClass, Object... args) {
                        // 如果是会员，则调用通知
                        Object arg = args[0];
                        return arg instanceof Member;
                    }
                };
            }
        };

        // 创建Advice，在方法之前调用，给会员一个通知
        MethodBeforeAdvice advice = (method, args, target) -> {
            Object arg = args[0];
            Member member = (Member) arg;
            System.out.println("你好:" + member.getName());
        };

        // 创建Advisor，将pointcut和advice组装起来
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        // 通过spring提供的代理创建工来创建代理
        ProxyFactory proxyFactory = new ProxyFactory();
        // 为工厂指定目标对象
        proxyFactory.setTarget(userService);
        // 指定Advisor
        proxyFactory.addAdvisor(advisor);
        // 生成代理对象
        UserService userServiceProxy = (UserService) proxyFactory.getProxy();

        People member = new Member("Vhans");
        People tourists = new Tourists("jack");
        userServiceProxy.work(member);
        userServiceProxy.work(tourists);
    }
}
